package fr.umlv.m2.jee.spij.service.training.impl;

import fr.umlv.m2.jee.spij.persistence.schooling.Training;
import fr.umlv.m2.jee.spij.persistence.schooling.dao.HibernateTrainingDAO;
import fr.umlv.m2.jee.spij.service.training.DisplayTraining;
import fr.umlv.m2.jee.spij.service.training.IDisplayTrainingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Provides methods to retrieve trainings into databases from DAO.
 *
 * @author lounes
 */
@Service("defaultDisplayTrainingService")
public class DefaultDisplayTrainingService implements IDisplayTrainingService {

    /**
     * the training DAO.
     */
    @Autowired
    private HibernateTrainingDAO trainingDAO;

    /**
     * @param context
     *
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<DisplayTraining> getAllDisplayTraining(MessageContext context) {
        final List<Training> trainingList = trainingDAO.findAll();

        final List<DisplayTraining> displayTrainingList = new ArrayList<DisplayTraining>();

        if (trainingList.isEmpty()) {
            context.addMessage(new MessageBuilder().info().code("units.empty").build());
        } else {
            for (Training training : trainingList) {
                displayTrainingList.add(new DisplayTraining(training));
            }
        }
        return displayTrainingList;
    }

    /**
     * @param id
     * @param context
     *
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public DisplayTraining getTrainingById(long id, MessageContext context) {
        final Training training = trainingDAO.findById(id);
        if (training == null) {
            context.addMessage(new MessageBuilder().error().code("unit.empty").build());
        }
        return new DisplayTraining(training);
    }

    /**
     * @param displayTraining
     * @param context
     *
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public boolean createTraining(final DisplayTraining displayTraining, final MessageContext context) {

        final Training training = new Training();


        if (!displayTraining.getName().isEmpty()) {
            training.setName(displayTraining.getName());
        }
        if (displayTraining.getNbYear() > 0) {
            training.setNbYear(displayTraining.getNbYear());
        } else {

            // TODO validator dans la page plutot qu'ici ?
            context.addMessage(new MessageBuilder().error().code("training.NbYear.positive").build());
            return false;
        }

        // Checks whether a unit already exists
        for (Training persistTraining : trainingDAO.findAll()) {
            if (persistTraining.getName().equals(training.getName())) {
                context.addMessage(new MessageBuilder().error().arg(training.getName()).code("training.name.unique").build());
                return false;
            }
        }

        // persists the unit into the db and displays the valuable message context
        trainingDAO.persist(training);
        context.addMessage(new MessageBuilder().info().arg(training.getName()).code("training.persist").build());

        return true;
    }

    /**
     * @param id
     * @param context
     *
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public boolean deleteTrainingById(long id, final MessageContext context) {
        boolean hasBeenRemoved = false;
        final Training training = trainingDAO.findById(id);

        if (training != null) {
            context.addMessage(new MessageBuilder().info().arg(training.getName()).code("training.delete").build());
            trainingDAO.remove(training);
            hasBeenRemoved = true;
        }

        return hasBeenRemoved;
    }

    /**
     * @param modifiedTraining
     * @param context
     *
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public boolean updateTrainingById(final DisplayTraining modifiedTraining, final MessageContext context) {
        boolean hasBeenUpdated = false;
        final Training toMerge = trainingDAO.findById(modifiedTraining.getId());

        // TODO better validators
        if (modifiedTraining.getNbYear() <= 0) {
            context.addMessage(new MessageBuilder().error().code("training.NbYear.positive").build());
            return false;
        }

        if (toMerge != null) {
            if (!toMerge.getName().equals(modifiedTraining.getName())) {
                context.addMessage(new MessageBuilder().info().args(new Object[]{toMerge.getName(), modifiedTraining.getName()}).code("training.update.name").build());
                toMerge.setName(modifiedTraining.getName());
                hasBeenUpdated = true;
            }
            if (toMerge.getNbYear() != modifiedTraining.getNbYear()) {
                context.addMessage(new MessageBuilder().info().args(new Object[]{toMerge.getNbYear(), modifiedTraining.getNbYear()}).code("training.update.nbYear").build());
                toMerge.setNbYear(modifiedTraining.getNbYear());
                hasBeenUpdated = true;
            }

            trainingDAO.merge(toMerge);
        }

        if (!hasBeenUpdated) {
            context.addMessage(new MessageBuilder().error().defaultText("update failed").build());
        }

        return hasBeenUpdated;
    }


}
